﻿#region using

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

#endregion

namespace JupiterLibrary
{
    public struct MeshPart
    {
        public int StartIndex;
        public int VertexOffset;
        public int PrimitiveCount;
        public int NumVertices;
    }

    public class Mesh:IRenderObject
    {
        public VB VertexBuffer;

        public IB IndexBuffer;

        public MeshPart[] MeshParts;
        
        public Texture2D Texture;

        public Gizmo Gizmo;

        public Mesh()
        {
            VertexBuffer = Jupiter.Video.VertexBuffers.CreateAndAdd();
            IndexBuffer = Jupiter.Video.IndexBuffers.CreateAndAdd();
        }

        /// <summary>
        /// Crea una rectangulo con esta distribución de vértices
        /// 
        /// 1      3
        /// 
        /// 
        /// 0      2
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void CreateRectangleXY(float width,float height)
        {
            VB vb = VertexBuffer;
                
            vb.Position = new Vector3[4];

            vb.Color = new Color[4];

            for (int i = 0; i < 4; i++)
                vb.Color[i] = Color.White;

            IB ib = IndexBuffer;

            ib.Indices = new uint[6];

            ib.Indices[0] = 0;
            ib.Indices[1] = 1;
            ib.Indices[2] = 2;

            ib.Indices[3] = 2;
            ib.Indices[4] = 1;
            ib.Indices[5] = 3;

            Vector3 a, b, c, d;

            a = new Vector3(0, 0, 0);
            b = new Vector3(0, height, 0);
            c = new Vector3(width, 0, 0);
            d = new Vector3(width, height, 0);

            // Hacemos que el 0,0 sea el centro del objeto

            float cx = width / 2;
            float cy = height / 2;

            a.X -= cx;
            a.Y -= cy;
            b.X -= cx;
            b.Y -= cy;
            c.X -= cx;
            c.Y -= cy;
            d.X -= cx;
            d.Y -= cy;

            vb.Position[0] = a;
            vb.Position[1] = b;
            vb.Position[2] = c;
            vb.Position[3] = d;

            vb.Color[0] = Color.Black;
            vb.Color[1] = Color.Red;
            vb.Color[2] = Color.Blue;
        }

        public void Update(Node node)
        {
        }

        public void Draw(Node node)
        {
            VertexBuffer.SetToDevice();

            IndexBuffer.SetToDevice();

            if (MeshParts == null)
            {
                DrawMeshPart(node, 0, 0, VertexBuffer.Position.Length,IndexBuffer.Indices.Length / 3);
            }
            else
            {
                foreach (MeshPart meshPart in MeshParts)
                {
                    DrawMeshPart(node,meshPart.VertexOffset,meshPart.StartIndex,meshPart.NumVertices,meshPart.PrimitiveCount);
                }
            }

            if (Gizmo != null)
            {
                Gizmo.Draw(node);
            }
        }

        /// <summary>
        /// Devuelve la lista de triangulos en Local Space, sin aplicar ninguna matriz
        /// </summary>
        /// <returns></returns>
        public List<Triangle3> GetTriangles()
        {
            List<Triangle3> list = new List<Triangle3>();

            for (int i = 0; i < IndexBuffer.Indices.Length; i += 3)
            {
                Triangle3 tri = new Triangle3();

                tri.A = VertexBuffer.Position[IndexBuffer.Indices[i]];
                tri.B = VertexBuffer.Position[IndexBuffer.Indices[i + 1]];
                tri.C = VertexBuffer.Position[IndexBuffer.Indices[i + 2]];

                list.Add(tri);
            }

            return list;
        }

        void DrawMeshPart(Node node, int vertexOffset, int startIndex,int numVertices,int primitiveCount)
        {
            BasicEffect basicEffect = Jupiter.Video.BasicEffect;
            
            basicEffect.World = node.World;
            /*
            basicEffect.View = Matrix.CreateLookAt(
    new Vector3(0.0f, 0.0f, 3.0f),
    Vector3.Zero,
    Vector3.Up
    ); ;
            basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,Jupiter.Video.GraphicsDevice.Viewport.AspectRatio,1.0f,10.0f);
            */
            basicEffect.View = Jupiter.Video.GlobalRender.Camera.View;
            basicEffect.Projection = Jupiter.Video.GlobalRender.Camera.Projection;

            // GameEngine.Video.GraphicsDevice.RasterizerState.FillMode = FillMode.WireFrame;

            basicEffect.DiffuseColor = Vector3.One;
            basicEffect.LightingEnabled = false;
            
            basicEffect.VertexColorEnabled = VertexBuffer.HasColor;

            basicEffect.Texture = Texture;

            basicEffect.TextureEnabled = (basicEffect.Texture != null);

            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                Jupiter.Video.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,vertexOffset, 0, numVertices,startIndex, primitiveCount);
            }
        }        
    }
}
